﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;

namespace Sl.Caching
{
    /// <summary>
    /// 简单依赖缓存
    /// </summary>
    /// <typeparam name="TKey">键类型</typeparam>
    /// <typeparam name="TResult">返回的值</typeparam>
    public class DependValueCache<TKey, TResult> : IDependCache<TKey, TResult>
    {
        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public TResult Get(TKey key, Func<TResult> value)
        {
            return Gets(key, value);
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        private TResult Gets(TKey key, Func<TResult> value)
        {
            TResult tr = (TResult)HttpRuntime.Cache[key.ToString()];
            if (tr == null)
            {
                tr = value();
                HttpRuntime.Cache.Insert(key.ToString(), tr);
            }
            return tr;
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="idep">依赖缓存项</param>
        /// <returns></returns>
        public TResult Get(TKey key, Func<TResult> value, IEnumerable<string> idep)
        {
            return Gets(key, value, idep);
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="idep">依赖缓存项</param>
        /// <returns></returns>
        private TResult Gets(TKey key, Func<TResult> value, IEnumerable<string> idep)
        {
            TResult tr = (TResult)HttpRuntime.Cache[key.ToString()];
            if (tr == null)
            {
                tr = value();
                HttpRuntime.Cache.Insert(key.ToString(), tr, new CacheDependency(null, idep.ToArray<string>()));
            }
            return tr;
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="absoluteExpiration">绝对过期时间：设置绝对时间后，相对时间为空</param>
        /// <param name="slidingExpiration">相对过期时间:设置相对时间后，绝对时间为空</param>
        /// <returns></returns>
        public TResult Get(TKey key, Func<TResult> value, DateTime? absoluteExpiration, TimeSpan? slidingExpiration)
        {
            return Gets(key, value, absoluteExpiration, slidingExpiration);
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="absoluteExpiration">绝对过期时间：设置绝对时间后，相对时间为空</param>
        /// <param name="slidingExpiration">相对过期时间:设置相对时间后，绝对时间为空</param>
        /// <returns></returns>
        private TResult Gets(TKey key, Func<TResult> value, DateTime? absoluteExpiration, TimeSpan? slidingExpiration)
        {
            TResult tr = (TResult)HttpRuntime.Cache[key.ToString()];
            if (tr == null)
            {
                tr = value();
                if (absoluteExpiration == null && slidingExpiration != null)
                    HttpRuntime.Cache.Insert(key.ToString(), tr, null, Cache.NoAbsoluteExpiration, slidingExpiration.Value);
                else if (absoluteExpiration != null && slidingExpiration == null)
                    HttpRuntime.Cache.Insert(key.ToString(), tr, null, absoluteExpiration.Value, Cache.NoSlidingExpiration);
            }
            return tr;
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="idep">依赖缓存项</param>
        /// <param name="absoluteExpiration">绝对过期时间：设置绝对时间后，相对时间为空</param>
        /// <param name="slidingExpiration">相对过期时间:设置相对时间后，绝对时间为空</param>
        /// <returns></returns>
        public TResult Get(TKey key, Func<TResult> value, IEnumerable<string> idep, DateTime? absoluteExpiration, TimeSpan? slidingExpiration)
        {
            return Gets(key, value, idep, absoluteExpiration, slidingExpiration);
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="idep">依赖缓存项</param>
        /// <param name="absoluteExpiration">绝对过期时间：设置绝对时间后，相对时间为空</param>
        /// <param name="slidingExpiration">相对过期时间:设置相对时间后，绝对时间为空</param>
        /// <returns></returns>
        private TResult Gets(TKey key, Func<TResult> value, IEnumerable<string> idep, DateTime? absoluteExpiration, TimeSpan? slidingExpiration)
        {
            TResult tr = (TResult)HttpRuntime.Cache[key.ToString()];
            if (tr == null)
            {
                tr = value();
                if (absoluteExpiration == null && slidingExpiration != null)
                    HttpRuntime.Cache.Insert(key.ToString(), tr, new CacheDependency(null, idep.ToArray<string>()), Cache.NoAbsoluteExpiration, slidingExpiration.Value);
                else if (absoluteExpiration != null && slidingExpiration == null)
                    HttpRuntime.Cache.Insert(key.ToString(), tr, new CacheDependency(null, idep.ToArray<string>()), absoluteExpiration.Value, Cache.NoSlidingExpiration);
            }
            return tr;
        }

        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="key">键</param>
        public void Remove(TKey key)
        {
            HttpRuntime.Cache.Remove(key.ToString());
        }
    }
}
